﻿using Player;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class PlayerStateMachine<T> where T:struct
{
    Dictionary<T, IStateBase> stateLookup;
    IStateBase currentState;
    IStateBase lastState;

    public PlayerStateMachine()
    {
        stateLookup = new Dictionary<T, IStateBase>();
    }


    public void OnUpdate(params object[] obj)
    {
        if (currentState != null)
            currentState.OnUpdate(obj);
    }

    public void FixedUpdate()
    {
        if (currentState != null)
            currentState.OnFixedUpdate();
    }

    public void OnInterrupt()
    {
        if (currentState != null)
            currentState.Interrupt();
    }


    public void ChangeState(T newState)
    {
        if (stateLookup == null)
        {
            throw new Exception("States have not been configured, please call initialized before trying to set state");
        }

        if (!stateLookup.ContainsKey(newState))
        {
            throw new Exception("No state with the name " + newState.ToString() + " can be found. Please make sure you are called the correct type the statemachine was initialized with");
        }

        var nextState = stateLookup[newState];
        if (currentState == nextState) return;

        if (currentState != null)
            currentState.OnExit();
        lastState = currentState;
        currentState = nextState;
        if (currentState != null)
            currentState.OnEnter();
    }


    public T GetState()
    {
        T key = stateLookup.Where(q => q.Value == currentState).Select(q => q.Key).FirstOrDefault<T>();
        return key;
    }

    public void AddState(T key, IStateBase playerState)
    {
        if (stateLookup == null)
        {
            throw new Exception("States have not been configured, please call initialized before trying to set state");
        }
        if (stateLookup.ContainsKey(key))
        {
            throw new Exception("Exit with the name " + key.ToString());
        }
        if (!stateLookup.ContainsKey(key))
            stateLookup.Add(key, playerState);
    }

    public void RemoveState(T key, IStateBase playerState)
    {
        if (stateLookup == null)
        {
            throw new Exception("States have not been configured, please call initialized before trying to set state");
        }
        if (!stateLookup.ContainsKey(key))
        {
            throw new Exception("No state with the name " + key.ToString() + " can be found. Please make sure you are called the correct type the statemachine was initialized with");
        }
        if (stateLookup.ContainsKey(key))
            stateLookup.Add(key, playerState);
    }

}
